<script setup lang="ts">
import type { ITab } from '../../../store/tab'
import { EventName } from '../../../enums'
import useConfigStore from '../../../store/config'
import useMicroStore from '../../../store/micro'
import useTabStore from '../../../store/tab'

defineOptions({ name: 'AppTab' })

enum OperateType {
  REFRESH = 0,
  OTHER = 1,
  RIGHT = 2,
  LEFT = 3,
  ALL = 4,
}

const { getBus } = useMicroStore()
const tabStore = useTabStore()
const configStore = useConfigStore()

let draggedTab: ITab | null = null
const dragEnterCode = ref()
const tabsRef = ref<HTMLElement | null>(null)
const showLeftArrow = ref(false)
const showRightArrow = ref(false)

const customStyle = computed(() => {
  return {
    backgroundColor: configStore.getPageRegionColor.TAB.background,
    color: configStore.getPageRegionColor.TAB.text,
  }
})

function checkScroll() {
  if (!tabsRef.value)
    return

  const {
    scrollLeft,
    scrollWidth,
    clientWidth,
  } = tabsRef.value

  showLeftArrow.value = scrollLeft > 0
  showRightArrow.value = scrollLeft + clientWidth < scrollWidth
}

function onScrollTabs(direction: 'left' | 'right') {
  if (!tabsRef.value)
    return

  const scrollAmount = 200
  const currentScroll = tabsRef.value.scrollLeft

  tabsRef.value.scrollTo({
    left: direction === 'left'
      ? currentScroll - scrollAmount
      : currentScroll + scrollAmount,
    behavior: 'smooth',
  })
}

function onContextMenu(type: OperateType, tab: ITab) {
  if (type === OperateType.REFRESH) {
    getBus.emit(EventName.PAGE_REFRESH, { appCode: tab.appCode })
  }

  if (type === OperateType.OTHER)
    tabStore.removeOtherTabs(tab.code)

  if (type === OperateType.RIGHT)
    tabStore.removeRightTabs(tab.code)

  if (type === OperateType.LEFT)
    tabStore.removeLeftTabs(tab.code)

  if (type === OperateType.ALL)
    tabStore.removeAllTabs()

  tab.popoverVisible = false
}

function getContextList(tab: ITab) {
  const list = [{
    type: OperateType.OTHER,
    name: '关闭其他',
    popoverVisible: false,
  }, {
    type: OperateType.RIGHT,
    name: '关闭右侧所有',
    popoverVisible: false,
  }, {
    type: OperateType.LEFT,
    name: '关闭左侧所有',
    popoverVisible: false,
  }, {
    type: OperateType.ALL,
    name: '关闭全部',
    popoverVisible: false,
  }]

  return tab.code === tabStore.getCurrentTabCode
    ? [
        {
          type: OperateType.REFRESH,
          name: '重新加载',
          popoverVisible: false,
        },
        ...list,
      ]
    : list
}

function handleDragStart(event: DragEvent, tab: ITab) {
  draggedTab = tab
  event.dataTransfer?.setData('text/plain', tab.code)
}

function handleDragEnter(event: DragEvent, tab: ITab) {
  dragEnterCode.value = tab.code

  if (draggedTab && draggedTab.code !== tab.code) {
    event.preventDefault()
  }
}

function handleDrop(event: DragEvent, tab: ITab) {
  if (draggedTab?.code !== tab.code) {
    const tabs = tabStore.getTabs
    const fromIndex = tabs.findIndex(t => t.code === draggedTab?.code)
    const toIndex = tabs.findIndex(t => t.code === tab.code)

    if (fromIndex !== -1 && toIndex !== -1) {
      const newTabs = [...tabs]
      newTabs.splice(fromIndex, 1)
      newTabs.splice(toIndex, 0, draggedTab!)
      tabStore.updateTabs(newTabs)
    }
  }
  draggedTab = null
  dragEnterCode.value = null
}

getBus.on(EventName.CLOSE_TAB, ({
  tabCode,
  jumpTabCode,
  emitParams,
}: { tabCode?: string, jumpTabCode?: string, emitParams?: { eventName: string, params?: any } } = {}) => {
  tabStore.removeTab(tabCode || tabStore.getCurrentTabCode)

  if (jumpTabCode) {
    tabStore.changeTab(jumpTabCode)
  }

  if (emitParams)
    getBus.emit(emitParams.eventName, emitParams.params)
})

watch(() => tabStore.getTabs.length, () => {
  nextTick(checkScroll)
})

onMounted(() => {
  if (tabsRef.value) {
    tabsRef.value.addEventListener('scroll', checkScroll)
    nextTick(checkScroll)
  }
  window.addEventListener('resize', checkScroll)
})

onBeforeUnmount(() => {
  if (tabsRef.value) {
    tabsRef.value.removeEventListener('scroll', checkScroll)
  }
  window.removeEventListener('resize', checkScroll)
})

</script>

<template>
  <div
    class="app-tab-container"
    :style="customStyle"
  >
    <ElButton
      v-show="showLeftArrow"
      class="scroll-button scroll-left-button"
      type="primary"
      circle
      @click="onScrollTabs('left')"
    >
      <BaseIcon icon="carbon:chevron-left" />
    </ElButton>

    <div
      ref="tabsRef"
      class="app-tab"
    >
      <div
        v-for="tab in tabStore.getTabs"
        :key="tab.code"
        v-ripple
        class="app-tab__item font-medium"
        :class="{
          'is-active': tab.code === tabStore.currentTabCode,
          'is-drag-enter': tab.code === dragEnterCode,
        }"
        draggable="true"
        @dragstart="handleDragStart($event, tab)"
        @dragenter="handleDragEnter($event, tab)"
        @dragover.prevent
        @drop="handleDrop($event, tab)"
        @click="tabStore.changeTab(tab.code)"
      >
        <ElPopover
          v-model:visible="tab.popoverVisible"
          :teleported="true"
          trigger="contextmenu"
          popper-class="app-tab__context"
        >
          <ul>
            <li
              v-for="item in getContextList(tab)"
              :key="item.type"
              class="context-item"
              @click="onContextMenu(item.type, tab)"
            >
              {{ item.name }}
            </li>
          </ul>

          <template #reference>
            <div class="app-tab__content">
              <span>{{ tab.name }}</span>
              <button
                v-if="tabStore.getTabs.length > 1"
                class="i-carbon-close hover:i-carbon-close-filled"
                @click.stop="tabStore.removeTab(tab.code)"
              />
            </div>
          </template>
        </ElPopover>
      </div>
    </div>

    <ElButton
      v-show="showRightArrow"
      class="scroll-button scroll-right-button"
      type="primary"
      circle
      @click="onScrollTabs('right')"
    >
      <BaseIcon icon="carbon:chevron-right" />
    </ElButton>
  </div>
</template>

<style lang="less" scoped>
.app-tab-container {
  position: relative;
  inline-size: 100%;
  block-size: 100%;
  display: flex;
  align-items: end;
  border-block-end: 1px solid var(--el-border-color);
  padding-block-start: 8px;
}

.app-tab {
  display: grid;
  justify-content: start;
  block-size: 100%;
  inline-size: 100%;
  gap: 2rem;
  grid-auto-flow: column;
  overscroll-behavior-x: contain;
  padding-inline-end: 24px;
  padding-inline-start: 24px;
  scroll-snap-type: x mandatory;
  overflow-x: auto;
  scrollbar-width: none; /* Firefox */
}

.app-tab::-webkit-scrollbar {
  display: none;
}

.scroll-button {
  position: absolute;
  z-index: 10;
  inline-size: 28px;
  block-size: 28px;
  padding: 0;
  font-size: 12px;
  opacity: 0.9;

  &.scroll-left-button {
    inset-inline-start: 4px;
    inset-block-end: 4px;
  }

  &.scroll-right-button {
    inset-inline-end: 4px;
    inset-block-end: 4px;
  }
}

.app-tab__item {
  position: relative;
  display: flex;
  align-items: center;
  cursor: pointer;
  word-break: keep-all;
  border-top-left-radius: 12px;
  border-top-right-radius: 12px;
  border-block-start: 1px solid transparent;
  inline-size: max-content;
  scroll-snap-align: center;
  transition:
    transform 0.3s ease,
    color 0.3s ease,
    border-color 0.3s ease; /* 添加过渡效果 */
}

.app-tab__item.is-drag-enter {
  transform: translateZ(10px);
  background-color: var(--el-color-primary-light-9); // 浅色背景
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); // 添加阴影
  transition:
    transform 0.2s ease,
    background-color 0.2s ease,
    box-shadow 0.2s ease;
}

.app-tab__item.is-active {
  color: var(--el-color-primary);
  border-top-color: var(--el-color-primary);
  background-color: var(--el-bg-color);
  transform: translateX(0);

  &::before,
  &:after {
    content: '';
    position: absolute;
    inline-size: 10px;
    block-size: 10px;
    bottom: 0;
  }

  &::before {
    left: -10px;
    background: radial-gradient(circle at 0 0, transparent 10px, var(--el-bg-color) 10px);
  }

  &::after {
    right: -10px;
    background: radial-gradient(circle at 100% 0, transparent 10px, var(--el-bg-color) 10px);
  }
}

.app-tab__item:not(.is-active) {
  transform: translateX(10px);
}

.app-tab__item:not(.is-active):hover .app-tab__content {
  background-color: var(--el-color-primary);
}

.app-tab__content {
  display: grid;
  column-gap: 12px;
  grid-auto-flow: column;
  place-items: center;
  padding-block: 4px;
  padding-inline: 12px;
  border-radius: 12px;
}

.context-item {
  display: grid;

  cursor: pointer;

  padding-block: 8px;
  padding-inline: 0;
  place-items: center;

  &:hover {
    background-color: var(--el-bg-color-page);
  }
}
</style>
